package com.xcm.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xcm.annotation.Operate;
import com.xcm.constant.BaseConstant;
import com.xcm.constant.FileConstants;
import com.xcm.constant.SysUserConstants;
import com.xcm.dao.SysDepartmentMapper;
import com.xcm.dao.SysUserMapper;
import com.xcm.dao.UserRoleMapper;
import com.xcm.exception.ServiceException;
import com.xcm.model.SysDepartment;
import com.xcm.model.SysUser;
import com.xcm.model.UserRole;
import com.xcm.model.vo.SysUserVo;
import com.xcm.page.PageInfo;
import com.xcm.service.SysUserService;
import com.xcm.util.*;
import com.xcm.validator.SysUserValidator;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * 用户服务实现
 *
 * @author 林强
 * @date 2018-04-12 11:15
 */
@Service(value = "sysUserService")
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysDepartmentMapper sysDepartmentMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;

    /**
     * 登陆
     *
     * @param userName 用户名
     * @param password 密码
     * @param system   系统标识
     * @return
     */
    @Override
    public SysUserVo login(String userName, String password, String system) {
        return sysUserMapper.loginVo(userName, password);
    }

    /**
     * 登陆
     *
     * @param userName 用户名
     * @param password 密码
     * @return
     */
    @Override
    public SysUser login(String userName, String password) {
        return sysUserMapper.login(userName, password);
    }

    /**
     * 列表分页
     *
     * @param paramMap 参数
     * @param pageNum  第几页
     * @param pageSize 每页几条
     * @return
     */
    @Override
    public PageInfo<SysUserVo> listPage(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<SysUserVo> page = sysUserMapper.listPage(paramMap);
        return PageInfo.build(page);
    }

    /**
     * 查询集合
     *
     * @param paramMap 参数map
     * @return
     */
    @Override
    public List<SysUserVo> list(Map<String, Object> paramMap) {
        return sysUserMapper.list(paramMap);
    }

    /**
     * 新增
     *
     * @param sysUser
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("新增用户")
    @Override
    public int save(SysUser sysUser) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysUser.setCreateTime(System.currentTimeMillis());
        sysUser.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysUser.setCreateUserId(currentUser.getUserId());
        }
        sysUser.setAble("1");
        sysUser.setStatus("1");
        sysUser.setPassword(DigestUtils.md5Hex(sysUser.getPassword()));
        return sysUserMapper.save(sysUser);
    }

    /**
     * 新增返回带id
     *
     * @param sysUser
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("新增用户并返回id")
    @Override
    public SysUser saveAndGetId(SysUser sysUser) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysUser.setCreateTime(System.currentTimeMillis());
        sysUser.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysUser.setCreateUserId(currentUser.getUserId());
        }
        sysUser.setAble("1");
        sysUser.setStatus("1");
        sysUser.setPassword(DigestUtils.md5Hex(sysUser.getPassword()));
        int effectRow = sysUserMapper.saveAndGetId(sysUser);
        return effectRow > 0 ? sysUser : null;
    }

    /**
     * 新增用户(同时绑定角色)
     *
     * @param sysUser 新增的用戶对象
     * @param roleIds 角色id(多个以英文的逗号隔开)
     * @return
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("新增用户(同时绑定角色)")
    @Override
    public int save(SysUser sysUser, String roleIds) {
        // 新增用户
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysUser.setCreateTime(System.currentTimeMillis());
        sysUser.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysUser.setCreateUserId(currentUser.getUserId());
        }
        sysUser.setAble("1");
        sysUser.setStatus("1");
        sysUser.setPassword(sysUser.getPassword());
        int effectRow = sysUserMapper.saveAndGetId(sysUser);
        if (effectRow > 0 && StringUtils.isNotBlank(roleIds)) {
            // 给用户绑定角色
            saveUserRole(sysUser.getUserId(), roleIds);
        }
        return effectRow;
    }

    /**
     * 根据用户名查询用户
     *
     * @param userName 用户名
     * @return
     */
    @Override
    public SysUser getByUsername(String userName) {
        return sysUserMapper.getByUsername(userName);
    }

    /**
     * 根据用户名查询用户VO
     *
     * @param userName 用户名
     * @return
     */
    @Override
    public SysUserVo getByUsernameVo(String userName) {
        return sysUserMapper.getByUsernameVo(userName);
    }

    /**
     * 刪除用户（同时删除用户角色关联）
     *
     * @param id 删除的数据的id
     * @return 大于0成功，0失败
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("刪除用户（同时删除用户角色关联）")
    @Override
    public int deleteById(Integer id) {
        //删除用户角色关联
        userRoleMapper.deleteUserRole(null, id);
        return sysUserMapper.deleteById(id);
    }

    /**
     * 批量刪除用户（同时删除用户角色关联）
     *
     * @param userIdList 批量删除的用户id集合
     * @return 大于0成功，0失败
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("批量刪除用户（同时删除用户角色关联）")
    @Override
    public int batchDeleteById(List<Integer> userIdList) {
        int row = 0;
        for (int i = 0; i < userIdList.size(); i++) {
            row += deleteById(userIdList.get(i));
        }
        return row;
    }

    /**
     * 修改密码
     *
     * @param userId      用户id
     * @param newPassword 新密码
     * @return
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("修改密码")
    @Override
    public int changePassword(Integer userId, String newPassword) {
        return sysUserMapper.changePassword(userId, newPassword);
    }

    /**
     * 判断是否可删除
     *
     * @param userId 角色id
     * @return 可删除返回true, 反之false
     */
    @Override
    public boolean canDelete(Integer userId) {
        int count = userRoleMapper.countUserRole(null, userId);
        return count <= 0;
    }

    /**
     * 更新
     *
     * @param sysUser 更新的用户对象
     * @param roleIds 角色id(多个以英文的逗号隔开)
     * @return 1成功，0失败，-1新的用户名已存在
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("修改用户（包括拥有的角色）")
    @Override
    public int update(SysUser sysUser, String roleIds) throws ServiceException {
        SysUser sysUserOld = sysUserMapper.getById(sysUser.getUserId());
        if (!sysUserOld.getUserName().equalsIgnoreCase(sysUser.getUserName())) {
            //用户名修改后判断是否已存在
            SysUser sysUserNew = sysUserMapper.getByUsername(sysUser.getUserName());
            if (null != sysUserNew) {
                throw new ServiceException(SysUserConstants.VALIDATE_USER_EXITS);
            }
        }
        int effectRow = update(sysUser);
        if (effectRow > 0) {
            //清除之前的角色
            userRoleMapper.deleteUserRole(null, sysUser.getUserId());
            if (StringUtils.isNotBlank(roleIds)) {
                //关联新的角色
                saveUserRole(sysUser.getUserId(), roleIds);
            }
        }
        return effectRow;
    }

    /**
     * 更新
     *
     * @param sysUser 更新的用户
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("修改用户")
    @Override
    public int update(SysUser sysUser) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysUser.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysUser.setUpdateUserId(currentUser.getUserId());
        }
        return sysUserMapper.update(sysUser);
    }

    /**
     * 根据id查询
     *
     * @param id 主键
     * @return
     */
    @Override
    public SysUser getById(Integer id) {
        return sysUserMapper.getById(id);
    }

    /**
     * 根据id查询VO
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public SysUserVo getByIdVo(Integer userId) {
        return sysUserMapper.getByIdVo(userId);
    }

    /**
     * 设置用户启用停用
     *
     * @param paramMap
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("单个启用或停用用户")
    @Override
    public int setEnableOrDisable(Map<String, Object> paramMap) {
        return sysUserMapper.setEnableOrDisable(paramMap);
    }

    /**
     * 批量启用用户
     *
     * @param userIdList 用户id数组
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("批量启用用户")
    @Override
    public int batchEnable(List<Integer> userIdList) {
        return sysUserMapper.setEnableOrDisableBatch(SysUserConstants.STATUS_ENABLE, userIdList);
    }

    /**
     * 批量停用用户
     *
     * @param userIdList 用户id数组
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("批量停用用户")
    @Override
    public int batchDisable(List<Integer> userIdList) {
        return sysUserMapper.setEnableOrDisableBatch(SysUserConstants.STATUS_DISABLE, userIdList);
    }

    /**
     * 批量导入用户
     *
     * @param file 文件
     * @return
     * @throws IOException
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Operate("批量导入用户")
    @Override
    public String importUserBatch(MultipartFile file) throws IOException {
        String result = "";
        String userNameErrorMsg = "";
        String userExitsErrorMsg = "";
        String passwordErrorMsg = "";
        String realNameErrorMsg = "";
        String departmentErrorMsg = "";
        String sexErrorMsg = "";
        String idCardErrorMsg = "";
        String emailErrorMsg = "";
        String phoneErrorMsg = "";
        int total = 0;
        int success = 0;
        if (null == file) {
            return FileConstants.NO_FILE;
        }
        if (file.isEmpty()) {
            return FileConstants.EMPTY_FILE;
        }
        File fileNew = ExcelUtils.multipartFileToFile(file);
        List<List<Object>> data = ExcelUtils.readExcel(fileNew);
        if (null != fileNew) {
            fileNew.delete();
        }
        if (CollectionUtils.isEmpty(data)) {
            return FileConstants.EMPTY_FILE;
        }
        total = data.size();
        if (total <= 0) {
            return FileConstants.EMPTY_FILE;
        }
        Map<String, SysUser> sysUserMap = new HashMap<>(total);
        for (int i = 0; i < data.size(); i++) {
            List<Object> row = data.get(i);
            if (null != row) {
                //用户名(5-20位,英文开头) 密码(6-20位,数字和字母组合) 真实姓名 性别	部门(多个以英文逗号隔开) 岗位 民族 身份证号码 邮箱 电话
                String userName = row.get(0).toString();
                String password = row.get(1).toString();
                String realName = row.get(2).toString();
                String sex = row.get(3).toString();
                String departmentName = row.get(4).toString();
                String post = row.get(5).toString();
                String nation = row.get(6).toString();
                String idCard = row.get(7).toString();
                String email = row.get(8).toString();
                String telephone = row.get(9).toString();
                if (!SysUserValidator.isUsername(userName)) {
                    userNameErrorMsg += (i + 2) + ",";
                    continue;
                }
                if (!SysUserValidator.isPassword(password)) {
                    passwordErrorMsg += (i + 2) + ",";
                    continue;
                }
                if (StringUtils.isBlank(realName)) {
                    realNameErrorMsg += (i + 2) + ",";
                    continue;
                }
                if (StringUtils.isNotBlank(sex) && !SysUserValidator.isSex(sex)) {
                    sexErrorMsg += (i + 2) + ",";
                    continue;
                }
                //检查部门
                String departMentIdStr = "";
                if (StringUtils.isNotBlank(departmentName)) {
                    SysDepartment sysDepartment = sysDepartmentMapper.getByName(departmentName);
                    if (null == sysDepartment) {
                        departmentErrorMsg += (i + 2) + ",";
                        continue;
                    }
                    departMentIdStr = sysDepartment.getDepartmentId().toString();
                }
                if (StringUtils.isNotBlank(idCard) && !IdcardUtils.isIDCard(idCard)) {
                    idCardErrorMsg += (i + 2) + ",";
                    continue;
                }
                if (StringUtils.isNotBlank(email) && !SysUserValidator.isEmail(email)) {
                    emailErrorMsg += (i + 2) + ",";
                    continue;
                }
                if (StringUtils.isNotBlank(telephone) && !SysUserValidator.isMobile(telephone)) {
                    phoneErrorMsg += (i + 2) + ",";
                    continue;
                }
                SysUser sysUser = new SysUser();
                sysUser.setUserName(userName);
                sysUser.setPassword(password);
                sysUser.setRealName(realName);
                sysUser.setSex(sex);
                if (StringUtils.isNotBlank(departMentIdStr)) {
                    sysUser.setDepartmentId(departMentIdStr);
                }
                sysUser.setEmail(email);
                sysUser.setIdCard(idCard);
                sysUser.setNation(nation);
                sysUser.setTelephone(telephone);
                sysUser.setPost(post);
                sysUser.setAble(SysUserConstants.STATUS_ENABLE);
                sysUser.setStatus(SysUserConstants.STATUS_ENABLE);
                sysUser.setCreateTime(System.currentTimeMillis());
                sysUser.setUpdateTime(System.currentTimeMillis());
                sysUserMap.put(String.valueOf(i + 2), sysUser);
            }
        }
        if (null != sysUserMap && !sysUserMap.isEmpty()) {
            for (Map.Entry<String, SysUser> entry : sysUserMap.entrySet()) {
                SysUser sysUser = sysUserMapper.getByUsername(entry.getValue().getUserName());
                if (null != sysUser) {
                    userExitsErrorMsg += entry.getKey() + ",";
                    continue;
                }
                DigestUtils.md5Hex(entry.getValue().getPassword());
                sysUserMapper.save(entry.getValue());
                success++;
            }
        }
        if (StringUtils.isNotBlank(userNameErrorMsg)) {
            result += "第" + userExitsErrorMsg.substring(0, userNameErrorMsg.length() - 1) + "行用户名格式错误(格式：英文开头，长度5-20位)";
        }
        if (StringUtils.isNotBlank(userExitsErrorMsg)) {
            result += "第" + userExitsErrorMsg.substring(0, userExitsErrorMsg.length() - 1) + "行用户已存在";
        }
        if (StringUtils.isNotBlank(passwordErrorMsg)) {
            result += "第" + passwordErrorMsg.substring(0, passwordErrorMsg.length() - 1) + "行密码格式错误(格式：数字英文组合，长度5-20位)";
        }
        if (StringUtils.isNotBlank(realNameErrorMsg)) {
            result += "第" + realNameErrorMsg.substring(0, realNameErrorMsg.length() - 1) + "行真实姓名不能为空";
        }
        if (StringUtils.isNotBlank(departmentErrorMsg)) {
            result += "第" + departmentErrorMsg.substring(0, departmentErrorMsg.length() - 1) + "行部门错误";
        }
        if (StringUtils.isNotBlank(sexErrorMsg)) {
            result += "第" + sexErrorMsg.substring(0, sexErrorMsg.length() - 1) + "行性别错误";
        }
        if (StringUtils.isNotBlank(idCardErrorMsg)) {
            result += "第" + idCardErrorMsg.substring(0, idCardErrorMsg.length() - 1) + "行身份证错误";
        }
        if (StringUtils.isNotBlank(emailErrorMsg)) {
            result += "第" + emailErrorMsg.substring(0, emailErrorMsg.length() - 1) + "行邮箱错误";
        }
        if (StringUtils.isNotBlank(phoneErrorMsg)) {
            result += "第" + phoneErrorMsg.substring(0, phoneErrorMsg.length() - 1) + "行电话错误";
        }
        if (StringUtils.isNotBlank(result)) {
            return FileConstants.IMPORT_FAIL + BaseConstant.COMMA_EN + result;
        }
        return FileConstants.IMPORT_SUCCESS + ",总共" + total + "条，成功" + success + "条。" + result;
    }

    /**
     * 给用户绑定角色
     *
     * @param userId  用户id
     * @param roleIds 角色id(多个以英文逗号隔开)
     */
    private void saveUserRole(Integer userId, String roleIds) {
        // 给用户绑定角色
        roleIds = roleIds.trim();
        if (roleIds.contains(BaseConstant.COMMA_ZH)) {
            //中文逗号改为英文逗号
            roleIds = roleIds.replaceAll(BaseConstant.COMMA_ZH, BaseConstant.COMMA_EN);
        }
        roleIds = CheckUtil.removeLastChar(BaseConstant.COMMA_EN, roleIds);
        String[] roleIdArr = roleIds.split(BaseConstant.COMMA_EN);
        TreeSet<String> roleIdSet = new TreeSet<>(Arrays.asList(roleIdArr));
        List<UserRole> userRoleList = new ArrayList<>();
        for (String roleId : roleIdSet) {
            UserRole userRole = new UserRole(userId, Integer.parseInt(roleId));
            userRoleList.add(userRole);
        }
        if (CollectionUtils.isNotEmpty(userRoleList)) {
            userRoleMapper.batchSave(userRoleList);
        }
    }
}
